#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include <pthread.h>
#define NUM_THREADS 6

using namespace std;

void *setaN(void *);
void *setaA(void *);
void *setaB(void *);
void *setaP(void *);
void *calculaB(void *);
void *calculaA(void *);
void *calculaP(void *);

typedef struct{
	long double a, b, p;
}var;

int main(int argc,char**argv){


	int N;
	var a;	// variaveis do algoritmo
	

	pthread_t threads[NUM_THREADS];
	pthread_create(&threads[0], NULL, setaN, (void*)&N);
	pthread_create(&threads[1], NULL, setaA, (void*)&a.a);
	pthread_create(&threads[2], NULL, setaB, (void*)&a.b);
	pthread_create(&threads[3], NULL, setaP, (void*)&a.p);

	/*
    pthread_join(threads[0], NULL);
    pthread_join(threads[1], NULL);
    pthread_join(threads[2], NULL);
    pthread_join(threads[3], NULL);
    */

	for(int i = 0; i < N; i++){
		
        pthread_create(&threads[4], NULL, calculaB, (void*)&a);
        pthread_join(threads[4], NULL);
        pthread_create(&threads[5], NULL, calculaA, (void*)&a);
//        pthread_join(threads[4], NULL);
		pthread_join(threads[5], NULL);
		pthread_create(&threads[6], NULL, calculaP, (void*)&a);
		pthread_join(threads[6], NULL);
	}

	cout.precision(7);
	cout << "pi:" << a.p << endl;

	return 0;
}


void *setaN(void *N){
    int *aux = (int *)N;
    *aux = 1000000;
    pthread_exit(NULL);
}

void *setaA(void *a){
    long double *aux = (long double*) a;
    
    // a = sqrt(2);
    *aux = sqrt(2);
    pthread_exit(NULL);
}

void *setaB(void *b){
    long double *aux = (long double*)b;
    
    // b = 0;
    *aux = 0;
    pthread_exit(NULL);
}

void *setaP(void *p){
    long double *aux = (long double*)p;
    
    // p = 2 + sqrt(2);
    *aux = 2 + sqrt(2);
    pthread_exit(NULL);
}

void *calculaB(void *v){
	var *f = (var*)v;
	long double aux = f->a;
	long double aux2 = f->b;
	
	// b = (sqrt(a * (1 + b))) / (a + b);  
    aux2 = (sqrt(aux) * (1 + (aux2))) / ((aux) + (aux2));
    f->b = aux2;
    pthread_exit(NULL);
}

void *calculaA(void *v){
	var *f = (var*)v;
    long double aux = f->a;
    long double aux2 = f->b;
    
    // a = (sqrt(a) / 2) + (1 / (2 * sqrt(a)));
    aux =((sqrt(aux)) / 2) + (1 / (2 * sqrt(aux)));
    f->a = aux;
     pthread_exit(NULL);
}


void *calculaP(void *v){
	var *f = (var*)v;
    long double aux = f->a;
    long double aux2 = f->b;
    long double aux3 = f->p;
    
    // p = (p * b) * (1 + a) / (1 + b);
    aux3 = (aux3 * aux2) * (1 + aux) / (1 + aux2);
    f->p = aux3;
    pthread_exit(NULL);
}

